package com.fan.cachewebview.core

import android.content.Context
import android.webkit.WebResourceResponse
import com.fan.cachewebview.core.interceptor.DiskInterceptor
import com.fan.cachewebview.bean.WebResource
import com.fan.cachewebview.bean.CacheRequest
import com.fan.cachewebview.core.interceptor.*

/**
 * @description
 * @date: 2022/2/23 15:57
 * @author: fan
 */
class LocalCacheImpl internal constructor(context: Context?, cacheConfig: CacheConfig?) :
    LocalCacheApi {

    private var mContext: Context? = context
    private var mCacheConfig: CacheConfig? = cacheConfig

    private var mWebResourceGenerator: WebResourceGenerateApi? = null


    private var mBaseInterceptorList: MutableList<ResourceInterceptor>? = null
    private var mCacheModeChainList: MutableList<ResourceInterceptor>? = null
    private var mNoCacheModeChainList: MutableList<ResourceInterceptor>? = null


    /**
     * 获取返回资源
     */
    override fun get(request: CacheRequest): WebResourceResponse? {
        val isCacheMode = request.isCacheMode
        val context = mContext!!
        val config = mCacheConfig!!

        val interceptors: List<ResourceInterceptor> = if (isCacheMode) buildCacheModeChain(
            context,
            config
        ) else {
            buildNoCacheModeChain(context)
        }

        // 调用责任链
        val resource: WebResource? = callChain(interceptors, request)

        return mWebResourceGenerator?.generate(resource, request.mime)
    }


    @Synchronized
    override fun destroy() {
        destroyAll(mNoCacheModeChainList)
        destroyAll(mCacheModeChainList)
    }

    private fun buildCacheModeChain(
        context: Context,
        cacheConfig: CacheConfig
    ): List<ResourceInterceptor> {
        if (mCacheModeChainList == null) {
            val interceptorsCount: Int = 3 + getBaseInterceptorsCount()
            val interceptors: MutableList<ResourceInterceptor> = ArrayList(interceptorsCount)
            if (mBaseInterceptorList != null && mBaseInterceptorList!!.isNotEmpty()) {
                interceptors.addAll(mBaseInterceptorList!!)
            }
            interceptors.add(MemInterceptor.getInstance(cacheConfig))
            interceptors.add(DiskInterceptor(cacheConfig))
            interceptors.add(FilterInterceptor(context, cacheConfig))
            mCacheModeChainList = interceptors
        }
        return mCacheModeChainList!!
    }


    private fun callChain(
        interceptors: List<ResourceInterceptor>,
        request: CacheRequest
    ): WebResource? {
        val chain = Chain(interceptors)
        return chain.process(request)
    }

    /**
     * 构建无Cache模式
     */
    private fun buildNoCacheModeChain(context: Context): List<ResourceInterceptor> {
        if (mNoCacheModeChainList == null) {
            var interceptorsCount = 1 + getBaseInterceptorsCount()
            var interceptors: MutableList<ResourceInterceptor> = ArrayList(interceptorsCount)
            if (mBaseInterceptorList != null && mBaseInterceptorList!!.isNotEmpty()) {
                interceptors.addAll(mBaseInterceptorList!!)
            }
            interceptors.add(NoCacheResourceInterceptor(context))
            mNoCacheModeChainList = interceptors
        }
        return mNoCacheModeChainList!!
    }

    @Synchronized
    override fun addResourceInterceptor(interceptor: ResourceInterceptor) {
        if (mBaseInterceptorList == null) {
            mBaseInterceptorList = ArrayList()
        }
        mBaseInterceptorList!!.add(interceptor)
    }


    /**
     * 清空拦截器
     */
    private fun destroyAll(interceptors: List<ResourceInterceptor>?) {
        if (interceptors == null || interceptors.isEmpty()) {
            return
        }
        for (interceptor in interceptors) {
            if (interceptor is DestroyApi) {
                (interceptor as DestroyApi).destroy()
            }
        }
    }


    init {
        mWebResourceGenerator = WebResourceGenerator()
    }

    private fun getBaseInterceptorsCount(): Int {
        return mBaseInterceptorList?.size ?: 0
    }
}